﻿using Sandbox.Game.Entities;
using Sandbox.Game.Lights;
using VRage.Game.Entity;
using VRageMath;

namespace Vicizlat.MultifloorCargoElevator
{
    public partial class MultifloorCargoElevator
    {
        internal SetDigit SetDigit = new SetDigit();
        private MyEntity3DSoundEmitter SoundEmitter;
        private readonly MySoundPair ElevatorSound = new MySoundPair("ElevatorSound");
        private readonly MySoundPair ElevatorDing = new MySoundPair("ElevatorDing");
        private bool PlayDingSound;
        private MyLight[] Light = new MyLight[4];
        private Color CabinLightColor = new Color(255, 255, 255);
        private Color oldCabinLightColor;
        private bool CabinLightRangeChanged = true;
        private float CabinLightRange = 10;
        private float oldCabinLightRange;
        private bool CabinLightIntensityChanged = true;
        private float CabinLightIntensity = 5;
        private float oldCabinLightIntensity;
        private bool positionChanged = true;
        private float SoundVolume = 2;
        private float oldSoundVolume = 0;

        private void CheckFloorDisplays()
        {
            if (!CurrentFloorChanged) CurrentFloorChanged = CurrentFloor != oldCurrentFloor;
            if (!TargetFloorChanged) TargetFloorChanged = TargetFloor != oldTargetFloor;
            if (!FloorsChanged)
            {
                for (int i = 0; i <= 8; i++) FloorsChanged = Floor[i] != oldFloor[i];
            }
        }

        private void UpdateFloorDisplays()
        {
            if (CurrentFloorChanged)
            {
                SetDigit.Subpart(ElevatorCabin, "CurrentFloorDisplay_", CurrentFloor, Color.Orange, 1f);
                for (int i = 1; i <= FloorsCount; i++) SetDigit.Block(Floor[i - 1], "CurrentFloorDisplay_", CurrentFloor, Color.Orange, 1f);
                if (CurrentFloor == TargetFloor)
                {
                    SetDigit.Subpart(ElevatorCabin, "TargetFloorDisplay_", 8, Color.Black, 0f);
                    ElevatorCabin.SetEmissivePartsForSubparts("Moving", Color.Black, 1f);
                    ElevatorCabin.SetEmissivePartsForSubparts("MovingDown", Color.Black, 1f);
                    if (TargetBlock != null) TargetBlock.SetEmissiveParts("CallBtn", Color.Black, 0f);
                    ElevatorCabin.SetEmissivePartsForSubparts("LightFloor" + TargetFloor, Color.White, 1f);
                    ElevatorCabin.SetEmissivePartsForSubparts("LookingAtLightFloor" + TargetFloor, Color.Black, 0f);
                    for (int i = 1; i <= FloorsCount; i++)
                    {
                        if (Floor[i - 1] != null)
                        {
                            Floor[i - 1].SetEmissiveParts("Moving", Color.Black, 0f);
                            Floor[i - 1].SetEmissiveParts("MovingDown", Color.Black, 0f);
                            SetDigit.Block(Floor[i - 1], "TargetFloorDisplay_", 8, Color.Black, 0f);
                            SetDigit.Block(Floor[i - 1], "TargetFloorDisplayLower_", 8, Color.Black, 0f);
                        }
                    }
                }
                CurrentFloorChanged = false;
            }
            oldCurrentFloor = CurrentFloor;
            if (TargetFloorChanged)
            {
                SetDigit.Subpart(ElevatorCabin, "TargetFloorDisplay_", TargetFloor, Color.Orange, 1f);
                if (TargetBlock != null) TargetBlock.SetEmissiveParts("CallBtn", Color.Orange, 1f);
                ElevatorCabin.SetEmissivePartsForSubparts("LightFloor" + TargetFloor, Color.Orange, 1f);
                ElevatorCabin.SetEmissivePartsForSubparts("LookingAtLightFloor" + TargetFloor, Color.Orange, 1f);
                if (TargetFloor > CurrentFloor)
                {
                    ElevatorCabin.SetEmissivePartsForSubparts("Moving", Color.Orange, 1f);
                    ElevatorCabin.SetEmissivePartsForSubparts("MovingDown", Color.Black, 0f);
                    for (int i = 1; i <= FloorsCount; i++)
                    {
                        if (Floor[i - 1] != null)
                        {
                            SetDigit.Block(Floor[i - 1], "TargetFloorDisplay_", TargetFloor, Color.Orange, 1f);
                            SetDigit.Block(Floor[i - 1], "TargetFloorDisplayLower_", 8, Color.Black, 0f);
                            Floor[i - 1].SetEmissiveParts("Moving", Color.Orange, 1f);
                            Floor[i - 1].SetEmissiveParts("MovingDown", Color.Black, 0f);
                        }
                    }
                }
                else
                {
                    ElevatorCabin.SetEmissivePartsForSubparts("MovingDown", Color.Orange, 1f);
                    ElevatorCabin.SetEmissivePartsForSubparts("Moving", Color.Black, 0f);
                    for (int i = 1; i <= FloorsCount; i++)
                    {
                        if (Floor[i - 1] != null)
                        {
                            SetDigit.Block(Floor[i - 1], "TargetFloorDisplayLower_", TargetFloor, Color.Orange, 1f);
                            SetDigit.Block(Floor[i - 1], "TargetFloorDisplay_", 8, Color.Black, 0f);
                            Floor[i - 1].SetEmissiveParts("MovingDown", Color.Orange, 1f);
                            Floor[i - 1].SetEmissiveParts("Moving", Color.Black, 0f);
                        }
                    }
                }
                TargetFloorChanged = false;
            }
            oldTargetFloor = TargetFloor;
            if (FloorsChanged)
            {
                for (int i = 1; i <= 9; i++)
                {
                    if (i <= FloorsCount)
                    {
                        if (Floor[i - 1] != null)
                        {
                            ElevatorCabin.SetEmissivePartsForSubparts("LightFloor" + i, Color.White, 1f);
                            SetDigit.Block(Floor[i - 1], "ThisFloorDisplay_", i, Color.Orange, 1f);
                        }
                    }
                    else ElevatorCabin.SetEmissivePartsForSubparts("LightFloor" + i, Color.Black, 0f);
                    ElevatorCabin.SetEmissivePartsForSubparts("LookingAtLightFloor" + i, Color.Black, 0f);
                }
                FloorsChanged = false;
            }
            for (int i = 0; i <= 8; i++) oldFloor[i] = Floor[i];
        }

        private void InitExtras()
        {
            SoundEmitter = new MyEntity3DSoundEmitter(Elevator_block as MyEntity, dopplerScaler: 0) { CustomMaxDistance = 20f };
            for (int i = 0; i <= 3; i++)
            {
                Light[i] = MyLights.AddLight();
                Light[i].Falloff = 3f;
                Light[i].LightOn = true;
                Light[i].Start("Light" + i);
            }
        }

        private void UpdateExtras()
        {
            if (PlayDingSound)
            {
                SoundEmitter.PlaySound(ElevatorDing, stopPrevious: true, alwaysHearOnRealistic: true);
                PlayDingSound = false;
            }
            if (Elevator_block.Enabled && !SoundEmitter.IsPlaying) SoundEmitter.PlaySound(ElevatorSound, alwaysHearOnRealistic: true);
            if (!Elevator_block.Enabled && SoundEmitter.IsPlaying && SoundEmitter.SoundPair == ElevatorSound) SoundEmitter.StopSound(true);

            if (ElevatorCabin != null && !ElevatorCabin.Closed)
            {
                if (AllEntitiesContained)
                {
                    for (int i = 0; i <= 3; i++) Light[i].Color = CabinLightColor;
                    ElevatorCabin.SetEmissiveParts("Light", CabinLightColor, 0.01f);
                }
                else
                {
                    if (RedLightWhenIntersecting)
                    {
                        for (int i = 0; i <= 3; i++) Light[i].Color = Color.Red;
                        ElevatorCabin.SetEmissiveParts("Light", Color.Red, 0.01f);
                    }
                }

                if (CabinLightRangeChanged)
                {
                    for (int i = 0; i <= 3; i++) Light[i].Range = CabinLightRange;
                }
                if (CabinLightIntensityChanged)
                {
                    for (int i = 0; i <= 3; i++) Light[i].Intensity = CabinLightIntensity;
                }
                if (positionChanged)
                {
                    Light[0].Position = CabinPosition + (ElevatorCabin.WorldMatrix.Forward * 4f) + (ElevatorCabin.WorldMatrix.Right * 4f) + (ElevatorCabin.WorldMatrix.Up * 1.25f);
                    Light[1].Position = CabinPosition + (ElevatorCabin.WorldMatrix.Forward * 4f) + (ElevatorCabin.WorldMatrix.Left * 4f) + (ElevatorCabin.WorldMatrix.Up * 1.25f);
                    Light[2].Position = CabinPosition + (ElevatorCabin.WorldMatrix.Backward * 4f) + (ElevatorCabin.WorldMatrix.Right * 4f) + (ElevatorCabin.WorldMatrix.Up * 1.25f);
                    Light[3].Position = CabinPosition + (ElevatorCabin.WorldMatrix.Backward * 4f) + (ElevatorCabin.WorldMatrix.Left * 4f) + (ElevatorCabin.WorldMatrix.Up * 1.25f);
                    SoundEmitter.SetPosition(CabinPosition);
                    SoundEmitter.CustomVolume = SoundVolume;
                    SoundEmitter.Update();
                }
                if (positionChanged || CabinLightRangeChanged || CabinLightIntensityChanged)
                {
                    for (int i = 0; i <= 3; i++) Light[i].UpdateLight();
                }
                if (positionChanged) positionChanged = false;
            }
        }
    }
}